using BackOffice.Application.DTOs;
using Backoffice.Domain.Repositories;
using Backoffice.Domain.Entities.App;

namespace BackOffice.Application.Services;

public class LogService : ILogService
{
    private readonly IRepository<AppSystem> _systemRepo;

    public LogService(IRepository<AppSystem> systemRepo)
    {
        _systemRepo = systemRepo;
    }

    public async Task<object> GetLogsAsync(DateTime? startDate, DateTime? endDate, string? username, string? action, string? level = null, int page = 1, int pageSize = 20)
    {
        var systems = await _systemRepo.GetAllAsync();
        var logs = systems.Where(s => s.Type == "Log").ToList();

        // 应用过滤条件
        if (startDate.HasValue)
            logs = logs.Where(l => l.CreatedAt >= startDate.Value).ToList();
        
        if (endDate.HasValue)
            logs = logs.Where(l => l.CreatedAt <= endDate.Value).ToList();
        
        if (!string.IsNullOrEmpty(username))
            logs = logs.Where(l => l.Name.Contains(username, StringComparison.OrdinalIgnoreCase)).ToList();
        
        if (!string.IsNullOrEmpty(action))
            logs = logs.Where(l => l.Value.Contains(action, StringComparison.OrdinalIgnoreCase)).ToList();

        if (!string.IsNullOrEmpty(level))
            logs = logs.Where(l => ExtractLogLevel(l.Value) == level).ToList();

        // 分页
        var total = logs.Count;
        var pagedLogs = logs
            .OrderByDescending(l => l.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToList();

        return new
        {
            total = total,
            page = page,
            pageSize = pageSize,
            totalPages = (int)Math.Ceiling((double)total / pageSize),
            logs = pagedLogs.Select(l => new
            {
                id = l.Id,
                username = l.Name,
                action = l.Value,
                level = ExtractLogLevel(l.Value),
                description = ExtractLogDescription(l.Description),
                ipAddress = ExtractIpAddress(l.Description),
                userAgent = ExtractUserAgent(l.Description),
                createdAt = l.CreatedAt,
                createdAtFormatted = l.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss")
            })
        };
    }

    public async Task<object> RecordLogAsync(LogRecordDto dto)
    {
        // 改进日志描述格式，使其更易读
        var description = string.IsNullOrEmpty(dto.Description) 
            ? $"{dto.IpAddress}|{dto.UserAgent}"
            : $"{dto.Description}|{dto.IpAddress}|{dto.UserAgent}";

        var logEntry = new AppSystem(
            dto.Username,
            dto.Action,
            description,
            "Log"
        );

        await _systemRepo.CreateAsync(logEntry);

        return new { Message = "日志记录成功", Id = logEntry.Id };
    }

    public async Task<byte[]> ExportLogsAsync(DateTime? startDate, DateTime? endDate, string? level = null)
    {
        var systems = await _systemRepo.GetAllAsync();
        var logs = systems.Where(s => s.Type == "Log").ToList();

        if (startDate.HasValue)
            logs = logs.Where(l => l.CreatedAt >= startDate.Value).ToList();
        
        if (endDate.HasValue)
            logs = logs.Where(l => l.CreatedAt <= endDate.Value).ToList();

        if (!string.IsNullOrEmpty(level))
            logs = logs.Where(l => ExtractLogLevel(l.Value) == level).ToList();

        // 生成CSV格式
        var csvContent = "用户名,操作,级别,描述,IP地址,用户代理,创建时间\n";
        foreach (var log in logs.OrderByDescending(l => l.CreatedAt))
        {
            var logLevel = ExtractLogLevel(log.Value);
            var description = ExtractLogDescription(log.Description);
            var ipAddress = ExtractIpAddress(log.Description);
            var userAgent = ExtractUserAgent(log.Description);
            
            csvContent += $"\"{log.Name}\",\"{log.Value}\",\"{logLevel}\",\"{description}\",\"{ipAddress}\",\"{userAgent}\",\"{log.CreatedAt:yyyy-MM-dd HH:mm:ss}\"\n";
        }

        return System.Text.Encoding.UTF8.GetBytes(csvContent);
    }

    public async Task<object> CleanLogsAsync(DateTime beforeDate)
    {
        var systems = await _systemRepo.GetAllAsync();
        var logsToDelete = systems.Where(s => s.Type == "Log" && s.CreatedAt < beforeDate).ToList();

        foreach (var log in logsToDelete)
        {
            await _systemRepo.DeleteAsync(log.Id);
        }

        return new { Message = $"已清理 {logsToDelete.Count} 条日志记录" };
    }

    public async Task<object> GetLogStatisticsAsync()
    {
        var systems = await _systemRepo.GetAllAsync();
        var logs = systems.Where(s => s.Type == "Log").ToList();

        var now = DateTime.UtcNow;
        var today = now.Date;
        var weekStart = today.AddDays(-(int)today.DayOfWeek);
        var monthStart = new DateTime(today.Year, today.Month, 1);

        var statistics = new
        {
            total = logs.Count,
            today = logs.Count(l => l.CreatedAt >= today),
            thisWeek = logs.Count(l => l.CreatedAt >= weekStart),
            thisMonth = logs.Count(l => l.CreatedAt >= monthStart),
            levels = logs.GroupBy(l => ExtractLogLevel(l.Value))
                        .Select(g => new { level = g.Key, count = g.Count() })
                        .OrderByDescending(x => x.count),
            topUsers = logs.GroupBy(l => l.Name)
                          .Select(g => new { username = g.Key, count = g.Count() })
                          .OrderByDescending(x => x.count)
                          .Take(10),
            topActions = logs.GroupBy(l => l.Value)
                            .Select(g => new { action = g.Key, count = g.Count() })
                            .OrderByDescending(x => x.count)
                            .Take(10)
        };

        return statistics;
    }

    public async Task<object> GetLogsByLevelAsync(string level, int page = 1, int pageSize = 20)
    {
        var systems = await _systemRepo.GetAllAsync();
        var logs = systems.Where(s => s.Type == "Log" && ExtractLogLevel(s.Value) == level).ToList();

        var total = logs.Count;
        var pagedLogs = logs
            .OrderByDescending(l => l.CreatedAt)
            .Skip((page - 1) * pageSize)
            .Take(pageSize)
            .ToList();

        return new
        {
            total = total,
            page = page,
            pageSize = pageSize,
            level = level,
            logs = pagedLogs.Select(l => new
            {
                id = l.Id,
                username = l.Name,
                action = l.Value,
                description = ExtractLogDescription(l.Description),
                ipAddress = ExtractIpAddress(l.Description),
                userAgent = ExtractUserAgent(l.Description),
                createdAt = l.CreatedAt,
                createdAtFormatted = l.CreatedAt.ToString("yyyy-MM-dd HH:mm:ss")
            })
        };
    }

    /// <summary>
    /// 从日志描述中提取IP地址
    /// </summary>
    private string ExtractIpAddress(string? description)
    {
        if (string.IsNullOrEmpty(description))
            return "";

        var parts = description.Split('|');
        if (parts.Length >= 2)
        {
            // 格式：描述|IP地址|UserAgent 或 IP地址|UserAgent
            return parts[parts.Length - 2];
        }
        return "";
    }

    /// <summary>
    /// 从日志描述中提取用户代理
    /// </summary>
    private string ExtractUserAgent(string? description)
    {
        if (string.IsNullOrEmpty(description))
            return "";

        var parts = description.Split('|');
        if (parts.Length >= 1)
        {
            // 格式：描述|IP地址|UserAgent 或 IP地址|UserAgent
            return parts[parts.Length - 1];
        }
        return "";
    }

    /// <summary>
    /// 从日志描述中提取操作描述
    /// </summary>
    private string ExtractLogDescription(string? description)
    {
        if (string.IsNullOrEmpty(description))
            return "";

        var parts = description.Split('|');
        if (parts.Length >= 3)
        {
            // 格式：描述|IP地址|UserAgent
            return parts[0];
        }
        return "";
    }

    /// <summary>
    /// 从操作中提取日志级别
    /// </summary>
    private string ExtractLogLevel(string action)
    {
        if (action.Contains("错误", StringComparison.OrdinalIgnoreCase) || 
            action.Contains("error", StringComparison.OrdinalIgnoreCase))
            return "ERROR";
        
        if (action.Contains("警告", StringComparison.OrdinalIgnoreCase) || 
            action.Contains("warning", StringComparison.OrdinalIgnoreCase))
            return "WARNING";
        
        if (action.Contains("信息", StringComparison.OrdinalIgnoreCase) || 
            action.Contains("info", StringComparison.OrdinalIgnoreCase))
            return "INFO";
        
        if (action.Contains("调试", StringComparison.OrdinalIgnoreCase) || 
            action.Contains("debug", StringComparison.OrdinalIgnoreCase))
            return "DEBUG";
        
        return "INFO"; // 默认为INFO级别
    }
} 